using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX.Direct3D;
using System.Drawing;
using Microsoft.DirectX;
using Zsa.Emulation.PPU;

namespace Zsa.Emulation.Render.Video.Direct3d
{
    /// <summary>
    /// Renders using direct3d
    /// </summary>
    public class Dx3dGraphicRender : GraphicRender
    {
        #region Fields
        /// <summary>
        /// The render device.
        /// </summary>
        private Device _RenderDevice;
        private Dx3dRenderSettings _Settings;


        /// <summary>
        /// The texture for table one.
        /// </summary>
        private Texture _BackgroundTexture;

        /// <summary>
        /// The first sprite table.
        /// </summary>
        private Sprite _BackgroundSprite;

        /// <summary>
        /// True if is disposed.
        /// </summary>
        private bool _IsDisposed;
        
        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:D3dGraphicRender"/> class.
        /// </summary>
        public Dx3dGraphicRender(Dx3dRenderSettings settings)
            : base ( settings )
        {
            _Settings = settings;
        }
        #endregion Constructor

        #region Methods

        /// <summary>
        /// Called when [init].
        /// </summary>
        protected override void OnRecreateDevice()
        {
            if (SurfaceControl == null)
            {
                return;
            }

            try
            {
                // Create the device.
                _RenderDevice = new Device(
                    _Settings.DeviceIndex,
                    _Settings.D3dDeviceType,
                    SurfaceControl,
                    _Settings.CreateFlags,
                    _Settings.PresentParam
                    );

                _RenderDevice.DeviceReset += new EventHandler(RenderDevice_DeviceReset);

                //Viewport _ViewPort = new Viewport();
                //_ViewPort.MinZ = 0F;
                //_ViewPort.MaxZ = 0F;
                //_ViewPort.X = 0;
                //_ViewPort.Y = 0;
                //_ViewPort.Height = SurfaceControl.Height;
                //_ViewPort.Width = SurfaceControl.Width;
                //_RenderDevice.Viewport = _ViewPort;
                
                // Create the first texture.
                _BackgroundTexture = new Texture(
                    _RenderDevice,
                    256,
                    256,
                    0,
                    Usage.None,
                    Format.A8R8G8B8,//_Settings.TextureFormat,
                    Pool.Managed
                    );

                // Zoom by 4??
                //_RenderDevice.Transform.View = Matrix.Scaling(0, 4, 0);

                

                // Create the background vertex thingies.
                //CreateBackgroundVertexes();
                ////_RenderDevice.SetPaletteEntries(
            }
            catch ( Exception excep )
            {
                throw excep;
            }
        }

        private void RenderDevice_DeviceReset(object sender, EventArgs e)
        {
            
        }

        /// <summary>
        /// Initialize the graphic render.
        /// </summary>
        /// <param name="renderSettings"></param>
        protected override void OnUpdateRenderSettings(GraphicRenderSettings renderSettings)
        {
            Dx3dRenderSettings _SettingsTemp = renderSettings as Dx3dRenderSettings;
            if (_SettingsTemp == null)
            {
                throw new ArgumentException();
            }

            if ( !_Settings.Equals(_SettingsTemp) )
            {
                OnRecreateDevice();
            }
            _Settings = _SettingsTemp;
        }

        /// <summary>
        /// Called when [dispose].
        /// </summary>
        protected override void OnDispose()
        {

        }

        /// <summary>
        /// Draws the frame on to the screen.
        /// </summary>
        public override void DrawScreen()
        {


            


            // Read the tables from the ppu.
            // Merging pattern/attribute/name tables.
            try
            {
                // Create the tables.
                CreateTable();
            }
            catch (Exception excep)
            {
                Console.WriteLine(excep);
            }

            // Clear with the ppu background color.
            _RenderDevice.Clear(ClearFlags.Target, Ppu.BackgroundColor, 1.0f, 0);
            //Start the scene
            _RenderDevice.BeginScene();
            // Draw the background.
            RenderBackground();
            // Render the sprites.
            RenderSprites();
            //End the scene
            _RenderDevice.EndScene();
            //Present.
            _RenderDevice.Present();

            
            // Begin the scene.
          //  _RenderDevice.BeginScene();
          //  // Clear the screen with the ppu background color.
          //  _RenderDevice.Clear(ClearFlags.Target, Ppu.BackgroundColor, 1.0f, 0);


          //  //Device preset.
          ////  _RenderDevice.Present();
          //  // Draw from name table.
          //  RenderBackground();
          //  // Draw the sprites.
          //  RenderSprites();
          //  // End the scene.
          //  _RenderDevice.EndScene();
          //  _RenderDevice.Present();

            
            

        }



        /// <summary>
        /// Creates the table.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="texture">The texture.</param>
        private void CreateTable()
        {
            // Create the graphics stream.
            GraphicsStream _Stream =
                _BackgroundTexture.LockRectangle(
                    0,
                    LockFlags.None);

            SurfaceDescription _SurfaceDescription = _BackgroundTexture.GetLevelDescription(0);
            WriteTable(null, _Stream.InternalData, _SurfaceDescription.Width, 4);
            _BackgroundTexture.UnlockRectangle(0);
        }

        /// <summary>
        /// Renders the background.
        /// </summary>
        protected void RenderBackground()
        {
            float 
                _TableWidth = Width / 2,
                _TableHeight = Height / 2;

            //_RenderDevice.VertexFormat = VertexFormats.
            // The size of each section.
            SizeF _TableScreenSize = new SizeF(_TableWidth, _TableHeight);

            // The area to render.
            Rectangle _TextureArea = new Rectangle(0, 0, 256, 256);
            
            
            // Create the new sprite.
            using ( _BackgroundSprite = new Sprite(_RenderDevice) )
            {
                // Set the flags.
                _BackgroundSprite.Begin(Microsoft.DirectX.Direct3D.SpriteFlags.None);

                
                _BackgroundSprite.Draw2D(
                    _BackgroundTexture,
                    _TextureArea,
                    new SizeF(Width, Height*4),
                    new PointF(0, 0),
                    Color.White
                );

                //// Draw the first tile. 0,0
                //_SpriteTableOne.Draw2D(
                //    _TextureNameTableOne,
                //    _TextureArea,
                //    _TableScreenSize,
                //    new PointF(0,0),
                //    Color.White
                //);
                
                //// Draw the next tile 0,1
                //_SpriteTableOne.Draw2D(
                //    _TextureNameTableOne,
                //    _TextureArea,
                //    _TableScreenSize,
                //    new PointF(0, _TableHeight),
                //    Color.White
                //);

                //// Draw the next tile 1,0
                //_SpriteTableOne.Draw2D(
                //     _TextureNameTableTwo,
                //     _TextureArea,
                //     _TableScreenSize,
                //     new PointF(_TableWidth, 0),
                //     Color.White
                // );

                //// Draw the last tile 1,1
                //_SpriteTableOne.Draw2D(
                //    _TextureNameTableTwo,
                //    _TextureArea,
                //    _TableScreenSize,
                //    new PointF(_TableWidth, _TableHeight),
                //    Color.White
                //);
                

                _BackgroundSprite.End();
                    
            }


        }

        /// <summary>
        /// Renders the sprites.
        /// </summary>
        private void RenderSprites()
        {
        }


        private void Test()
        {

            Texture _Donut = TextureLoader.FromFile(_RenderDevice, @"..\..\..\donut.bmp", 320, 384,
                1, 0, Format.A8R8G8B8, Pool.Managed, Filter.Point, Filter.Point, (unchecked((int)0xff000000)));

            Texture _Text = new Texture(
                _RenderDevice, Bitmap.FromFile(@"..\..\..\donut.bmp") as Bitmap, Usage.None, Pool.Managed);


            //_RenderDevice.SamplerState[0].MinFilter = TextureFilter.None;
            //_RenderDevice.SamplerState[0].MagFilter = TextureFilter.None;
            Texture test4 = new Texture(_RenderDevice, 256, 256, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
            //Texture _T = TextureLoader.FromStream(
            //    _RenderDevice,
            //    TextureLoader.SaveToStream(ImageFileFormat.Bmp, _TextureNameTableOne)
            //);
            Texture _Texture = new Texture(_RenderDevice, 256, 256, 1, 0, Format.A8R8G8B8, Pool.Managed);



        }
        #endregion Methods

        #region Properties
        


        //public GraphicRenderSettings Settings
        //{
        //    get
        //    {
        //        return null;
        //    }
        //}
        #endregion Properties


       






    }


}
